#ifndef __OS_H__
#define __OS_H__

#include "types.h"
#include "platform.h"
#include "riscv.h"

#include <stddef.h>
#include <stdarg.h>

/* uart */
extern void uart_init(void);
extern int  uart_putc(char ch);
extern void uart_puts(char *s);

/* printf */
extern int  printf(const char* s, ...);
extern void panic(char *s);

/* memory management */
extern void page_init(void);
extern void *page_alloc(int npages);
extern void page_free(void *p);
extern void malloc_test(void);

/* task management */
struct context {
	/* ignore x0 */
	reg_t ra;
	reg_t sp;
	reg_t gp;
	reg_t tp;
	reg_t t0;
	reg_t t1;
	reg_t t2;
	reg_t s0;
	reg_t s1;
	reg_t a0;
	reg_t a1;
	reg_t a2;
	reg_t a3;
	reg_t a4;
	reg_t a5;
	reg_t a6;
	reg_t a7;
	reg_t s2;
	reg_t s3;
	reg_t s4;
	reg_t s5;
	reg_t s6;
	reg_t s7;
	reg_t s8;
	reg_t s9;
	reg_t s10;
	reg_t s11;
	reg_t t3;
	reg_t t4;
	reg_t t5;
	reg_t t6;

	/* save the pc(fact is epc) to run in next schedule cycle
	 * offset: 31 * sizeof(reg_t)
	 */
	reg_t pc; 

};

extern int  task_create(void (*task)(void));
extern void task_delay(volatile int count);
extern void sched_init(void);
extern void schedule(void);
extern void task_yield();
extern void os_main(void);


/* trap */
extern void trap_init(void);
extern void trap_test(void);
extern reg_t trap_handler(reg_t epc, reg_t cause);
extern void external_interrupt_handler(void);



/* plic */
extern void plic_init(void);
// extern void plic_enable_interrupt(int interrupt_id);
// extern void plic_disable_interrupt(int interrupt_id);
extern int  plic_claim(void);
extern void plic_complete(int interrupt_id);


/* timer */
extern void timer_init(void);
extern void timer_load(int interval);
extern void timer_handler(void);

#endif /* __OS_H__ */
